using System;

namespace Laba4
{
    public class MatrixMethods
    {
        private static double[,] MatrC(double[, ] MatrA){
            var MatrC = new double[MatrA.Length, MatrA.Length];
            for (int k = 0; k < MatrA.Length-1; k++)
            {
                double Akk = 0;
                for (int i = 0; i < MatrA.Length; i++)
                {
                    if (Akk < Math.Abs(MatrA[k, i]))
                        Akk = MatrA[k, i];
                }
                for (int i = k+1; i <MatrA.Length; i++)
                    MatrC[i, k] = MatrA[k, i] / Akk;
            }
            return MatrC;
        }

        private static double[,] MatrA(double[,] MatrA){
            var matrC = MatrC(MatrA);
            var matrA = new double[MatrA.Length, MatrA.Length];

            for (int k = 0; k < MatrA.Length-1; k++)
            {
                for (int i = k+1; i < MatrA.Length; i++)
                {
                    for (int j = k; j < MatrA.Length; j++)
                    {
                        matrA[i, j] = MatrA[i, j] - MatrA[k, j] * matrC[k, i];
                    } 
                }
            }
            return matrA;
        }
        private static double[] MatrB(double[,] MatrA, double[] MatrB){
            var matrC = MatrC(MatrA);
            var matrB = new double[MatrB.Length];

            for (int k = 0; k < MatrB.Length-1; k++)
            {
                for (int i = k+1; i < MatrB.Length; i++)
                {
                    matrB[i] = MatrB[i] - MatrB[k] * matrC[k, i];
                }
            }
            return matrB;
        }

        public static double[] GausMethod(double[,] matrA, double[]matrB)
        {
            matrA = MatrA(matrA);
            matrB = MatrB(matrA, matrB);
            double[] MatrX = new double[matrA.Length];
            MatrX[MatrX.Length - 1] = matrB[MatrX.Length - 1] / matrA[MatrX.Length - 1, MatrX.Length - 1];
            for (int i = MatrX.Length-2; i > -1; i--)
            {
                double b = 0;
                for (int j = i+1; j < MatrX.Length; j++)
                {
                    b += MatrX[j] * matrA[i, j];
                }
                MatrX[i] = (1/matrA[i, i])*(matrB[i] - b);
            }
            return MatrX;
        }

        private const double eps = 10e-5;

        public static bool Check(double[] Xk, double[] Xk1){
            for (int i = 0; i < Xk.Length; i++)
            {
                if (Math.Abs(Xk1[i] - Xk[i]) > eps)
                    return false;
            }
            return true;
        }

        public static bool Shodimost(double[][] MatrA)
        {
            for(int i = 0; i < MatrA.Length; i++){
                for(int j = 0 ; j< MatrA.Length; j++) if(Math.Abs(MatrA[i][i]) < Math.Abs(MatrA[i][j]))return false;
            }
            return true;
        }

        public static double[] SimpleIteration(double[][] MatrA, double[] MatrB, double[] MatrX)
        {
            var matrX = new double[MatrX.Length];
            for (int i = 0; i<matrX.Length; i++)
            {
                var result = 0d;
                for (int j =0; j < MatrX.Length; j++)
                {
                    result += MatrA[i][j] * MatrX[j];
                }
                matrX[i] = MatrX[i] - result / MatrA[i][i] - MatrB[i];
            }
            return matrX;
        }

        public static double[] Zeidel(double[, ] MatrA, double[] MatrB, double[] MatrX){
            var matrX = new double[MatrX.Length];
            for (int i = 0; i < MatrX.Length; i++)
                matrX[i] = 0;
            for (int i = 0; i < MatrX.Length; i++)
            {
                var result = 0d;
                for (int j = 0; j < matrX.Length; j++)
                {
                    result += MatrA[i, j] * (matrX[j] + MatrX[j]);
                }
                matrX[i] = MatrX[i] - result / MatrA[i, i] - MatrB[i];
            }
            return matrX;
        }
    }
}
